home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / pascal / swag / comm.swg / 0031_Very GOOD Async package.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-11-02  |  12.3 KB  |  322 lines

  1. {
  2. FRANCK DUMONT
  3.  
  4. ------------------------------------------ ASM ------------------------------
  5.  
  6. ;//////////////////////////////////////////////////////////////////////////
  7. ;///                                                                    ///
  8. ;///           Turbo-Pascal V24-Interrupt-Support      V2.00            ///
  9. ;///                                                                    ///
  10. ;///                 (c) Christian Philipps, Moers                      ///
  11. ;///                    June 1988 / West-Germany                        ///
  12. ;///                                                                    ///
  13. ;///                Turbo Pascal 4.0 or above required                  ///
  14. ;///                                                                    ///
  15. ;//////////////////////////////////////////////////////////////////////////
  16.  
  17. ; This module is hereby donated to the public domain.
  18.  
  19. ;─────────────────────────────────────────────────────────────────────────
  20. ;                    Datensegment
  21. ;─────────────────────────────────────────────────────────────────────────
  22.  
  23. DATA     SEGMENT BYTE PUBLIC
  24.  
  25.          ; Turbo-Pascal Variable
  26.          EXTRN V24HP      : WORD
  27.          EXTRN V24TP      : WORD
  28.          EXTRN V24BuffEnd : WORD
  29.          EXTRN V24Buff    : BYTE
  30.          EXTRN ComBase    : WORD
  31.  
  32. DATA     ENDS
  33.  
  34. ;─────────────────────────────────────────────────────────────────────────
  35. ;                        Codesegment
  36. ;─────────────────────────────────────────────────────────────────────────
  37.  
  38. CODE     SEGMENT BYTE PUBLIC
  39.  
  40.          ASSUME CS:CODE, DS:DATA
  41.  
  42.          PUBLIC V24Int
  43.  
  44. ;─────────────────────────────────────────────────────────────────────────
  45.  
  46. ;CS-relative Daten
  47.  
  48. _Turbo_DS DW  DATA                              ; Turbo data segment
  49.       ; (inserted by linkage editor)
  50.  
  51. ;─────────────────────────────────────────────────────────────────────────
  52. ;                    Codebereich
  53. ;─────────────────────────────────────────────────────────────────────────
  54. ;PROCEDURE V24Int; interrupt;
  55. ;  this routine is executed whenever a character arrives
  56.  
  57. V24Int   PROC  FAR                               ; Interrupt-Routine
  58.  
  59.  
  60. V24Int   ENDP
  61.  
  62.   push ds                                 ; save registers
  63.          push ax
  64.          push bx
  65.          push dx
  66.   mov  ds,CS:_Turbo_DS                    ; set Turbo DS
  67.  
  68.   mov  bx,V24TP                           ; ds:bx -> next free slot
  69.   mov  dx,ComBase                         ; dx = port base-address
  70.          in   al,dx                              ; RBR -> al
  71.   mov  byte ptr [bx],al                   ; move byte into buffer
  72.   inc  bx                                 ; pointer to next slot
  73.   cmp  bx,V24BuffEnd                      ; past the end of the buffer?
  74.   jle  L1                                 ; no
  75.   mov  bx,OFFSET V24Buff                  ; yes, so wrap around
  76.  
  77. L1:      cmp  bx,V24HP                           ; TP=HP --> overflow!
  78.   jz   L2                                 ; yes, ignore character
  79.   mov  V24TP,bx                           ; no, save new tail pointer
  80.  
  81. L2:      mov  al,20H                             ; EOI -> 8259
  82.          out  20H,al
  83.   pop  dx                                 ; restore registers
  84.          pop  bx
  85.          pop  ax
  86.          pop  ds
  87.          iret
  88.  
  89. CODE     ENDS
  90.  
  91. END
  92. }
  93. (*////////////////////////////////////////////////////////////////////////////
  94. ///                                                                        ///
  95. ///         T U R B O  -  P A S C A L  V24-Interrupt-Support V2.00         ///
  96. ///                (c) Copyright June 1988 by C.Philipps                   ///
  97. ///                                                                        ///
  98. ///               (Turbo Pascal V4.0  or higher required)                  ///
  99. ///                                                                        ///
  100. //////////////////////////////////////////////////////////////////////////////
  101. ///                                                                        ///
  102. ///            Low-level interrupt-handling for the serial ports. Speeds   ///
  103. ///            up to 115200 bps are supportet, one port at a time.         ///
  104. ///            Parts of the basics were taken from Mike Halliday's pop-    ///
  105. ///            ular ASYNC-package (Turbo Pascal 3.0, PD).                  ///
  106. ///                                                                        ///
  107. ///       This module is hereby donated to the public domain.              ///
  108. ///                                                                        ///
  109. ///       Christian Philipps                                               ///
  110. ///       Düsseldorfer Str. 316                                            ///
  111. ///       4130 Moers 1                                                     ///
  112. ///       West-Germany                                                     ///
  113. ///                                                                        ///
  114. ///       Last modified: 07/89                                             ///
  115. ///                                                                        ///
  116. ////////////////////////////////////////////////////////////////////////////*)
  117.  
  118. {$R-,S-,I-,D-,F-,V-,B-,N-,L- }
  119.  
  120. UNIT V24;
  121.  
  122. INTERFACE
  123.  
  124. USES
  125.   DOS;
  126.  
  127. TYPE
  128.   ComType      = (com1, com2, com3, com4, com5, com6);
  129.   BaudType     = (b110, b150, b300, b600, b1200, b2400, b4800,
  130.                   b9600, b19200, b38400, b57600, b115200);
  131.   ParityType   = (Space, Odd, Mark, Even, None);
  132.   DataBitsType = (d5, d6, d7, d8);
  133.   StopBitsType = (s1, s2);
  134.  
  135. CONST
  136.   V24Timeout : BOOLEAN = FALSE;  {SendByte-Timeout}
  137.   IntMasks   : ARRAY [Com1..Com6] OF WORD = ($EF,$F7,$EF,$F7,$EF,$F7);
  138.   IntVect    : ARRAY [Com1..Com6] OF BYTE = ($0C,$0B,$0C,$0B,$0C,$0B);
  139.  
  140. VAR
  141.   V24TP      : WORD; {Buffer Tail-Pointer Im Interface-Teil, da zur
  142.                       Ereignis-steuerung im Multi-Tasking benötigt.}
  143.   ComBaseAdr : ARRAY [Com1..Com6] OF WORD;
  144.  
  145. FUNCTION  V24DataAvail : BOOLEAN;
  146. FUNCTION  V24GetByte : BYTE;
  147. PROCEDURE InitCom(ComPort : ComType; Baudrate : BaudType; Parity : ParityType;
  148.                   Bits : DataBitsType; Stop : StopBitsType);
  149. PROCEDURE DisableCom;
  150. PROCEDURE SendByte(Data : BYTE);
  151.  
  152.  
  153. IMPLEMENTATION
  154.  
  155. CONST
  156.   Regs : Registers =
  157.     (AX : 0; BX : 0; CX : 0; DX : 0; BP : 0;
  158.      SI : 0; DI : 0; DS : 0; ES : 0; FLAGS : 0);
  159.   RBR = $00;          {xF8 Receive Buffer Register            }
  160.   THR = $00;          {xF8 Transmitter Holding Register       }
  161.   IER = $01;          {xF9 Interrupt Enable Register          }
  162.   IIR = $02;          {xFA Interrupt Identification Register  }
  163.   LCR = $03;          {xFB Line Control Register              }
  164.   MCR = $04;          {xFC Modem Control Register             }
  165.   LSR = $05;          {xFD Line Status Register               }
  166.   MSR = $06;          {xFE Modem Status Register              }
  167.                                   {--- if LCR Bit 7 = 1  ---              }
  168.   DLL = $00;          {xF8 Divisor Latch Low Byte             }
  169.   DLH = $01;          {xF9 Divisor Latch Hi  Byte             }
  170.   CMD8259 = $20;      {Interrupt Controller Command Register  }
  171.   IMR8259 = $21;      {Interrupt Controller Mask Register     }
  172.                       {Should be evaluated by any higher-level send-routine}
  173.   LoopLimit   = 1000; {When does a timeout-error occur        }
  174.   V24BuffSize = 2048; { Ringpuffer 2 KB }
  175.  
  176. VAR
  177.   BiosComBaseAdr : ARRAY [Com1..Com2] OF WORD ABSOLUTE $0040:$0000;
  178.   ActivePort     : ComType;
  179.   { The Com-Port base adresses are taken from the BIOS data area }
  180.   ComBase        : WORD;         {Hardware Com-Port Base Adress          }
  181.   OldV24         : Pointer;
  182.   V24HP          : WORD;         {Buffer Head-Pointer                    }
  183.   V24BuffEnd     : WORD;         {Buffer End-Adress                      }
  184.   V24Buff        : ARRAY [0..V24BuffSize] OF BYTE;
  185.   OExitHandler   : Pointer;    {Save-Area für Zeiger auf Org.-Exit-Proc}
  186.  
  187.  
  188. PROCEDURE V24Int; external;
  189. {$L v24.obj}
  190.  
  191.  
  192. PROCEDURE ClearPendingInterrupts;
  193. VAR
  194.   N : BYTE;
  195. BEGIN
  196.   WHILE (PORT[ComBase + IIR] AND 1) = 0 DO  {While Interrupts are pending}
  197.   BEGIN
  198.     N := PORT[ComBase + LSR];               {Read Line Status}
  199.     N := PORT[ComBase + MSR];               {Read Modem Status}
  200.     N := PORT[ComBase + RBR];               {Read Receive Buffer Register}
  201.     PORT[CMD8259] := $20;                   {End of Interrupt}
  202.   END;
  203. END;
  204.  
  205.  
  206. FUNCTION V24DataAvail:BOOLEAN;
  207. { This function checks, whether there are characters in the buffer }
  208. BEGIN
  209.   V24DataAvail := (V24HP <> V24TP);
  210. END;
  211.  
  212.  
  213. FUNCTION V24GetByte:BYTE;
  214. { Take a byte out of the ring-buffer and return it to the caller.
  215.   This function assumes, that the application has called V24DataAvail
  216.   before to assure, that there are characters available!!!!
  217.   The ISR only reads the current head-pointer value, so this routine
  218.   may modify the head-pointer with interrupts enabled. }
  219. BEGIN
  220.   V24GetByte := Mem[DSeg:V24HP];
  221.   Inc(V24HP);
  222.   IF V24HP > V24BuffEnd THEN
  223.     V24HP := Ofs(V24Buff);
  224. END;
  225.  
  226.  
  227. PROCEDURE SendByte(Data:BYTE);
  228. VAR
  229.   Count : BYTE;
  230. BEGIN
  231.   Count := 0;
  232.   V24Timeout := FALSE;
  233.   IF ComBase > 0 THEN
  234.   BEGIN
  235.     REPEAT
  236.       Count := SUCC(Count);
  237.     UNTIL ((PORT[ComBase + LSR] AND $20) <> 0) OR (Count > LoopLimit);
  238.     IF Count > LoopLimit THEN
  239.       V24Timeout := TRUE
  240.     ELSE
  241.       PORT[ComBase+THR] := Data;
  242.   END;
  243. END;
  244.  
  245.  
  246. PROCEDURE InitCom(ComPort : ComType; Baudrate : BaudType; Parity : ParityType;
  247.                   Bits : DataBitsType; Stop : StopBitsType);
  248. CONST
  249.   BaudConst   : ARRAY [b110..b115200] OF WORD =
  250.     ($417,$300,$180,$C0,$60,$30,$18,$0C,$06,$03,$02,$01);
  251.   ParityConst : ARRAY [Space..None] OF BYTE = ($38,$08,$28,$18,$00);
  252.   BitsConst   : ARRAY [d5..d8] OF BYTE = ($00,$01,$02,$03);
  253.   StopConst   : ARRAY [s1..s2] OF BYTE = ($00,$04);
  254. BEGIN
  255.   V24HP       := Ofs(V24Buff);
  256.   V24TP       := V24HP;
  257.   V24BuffEnd  := V24HP + V24BuffSize;
  258.   FillChar(V24Buff, Succ(V24BuffSize), #0);
  259.   V24Timeout := FALSE;                           {Reset Timeout-Marker}
  260.   ComBase := ComBaseAdr[ComPort];                {Get Com-Port base adress}
  261.   ActivePort := ComPort;                         {Keep Active-Port for EOI}
  262.   ClearPendingInterrupts;
  263.   GetIntVec(IntVect[ComPort], OldV24);
  264.   SetIntVec(IntVect[ComPort], @V24Int);
  265.                                                  {Install interrupt routine}
  266.   INLINE($FA);                                   {CLI}
  267.   PORT[ComBase + LCR] := $80;                    {Adress Divisor Latch}
  268.   PORT[ComBase + DLH] := Hi(BaudConst[Baudrate]);{Set Baud rate}
  269.   PORT[COMBase + DLL] := Lo(BaudConst[Baudrate]);
  270.   PORT[ComBase + LCR] := ($00 OR ParityConst[Parity] {Setup Parity}
  271.                             OR BitsConst[Bits]   {Setup number of databits}
  272.                             OR StopConst[Stop]); {Setup number of stopbits}
  273.   PORT[ComBase + MCR] := $0B;                    {Set RTS,DTR,OUT2}
  274. (*
  275.   PORT[ComBase+MCR] := $1B;                      {Set RTS,DTR,OUT2,Loop}
  276. *)
  277.   PORT[ComBase + IER] := $01; {Enable Data-Available Interrupts}
  278.   PORT[IMR8259] := PORT[IMR8259] AND IntMasks[ComPort]; {Enable V24-Interrups}
  279.   INLINE($FB);  {STI}
  280. END;
  281.  
  282.  
  283. PROCEDURE DisableCom;
  284. BEGIN
  285.   IF ComBase = 0 THEN
  286.     Exit;
  287.   INLINE($FA);                           {CLI}
  288.   PORT[ComBase + MCR] := 00;             {Disable Interrupts, Reset MCR}
  289.   PORT[IMR8259] := PORT[IMR8259] OR $18; {Disable Interrupt Level 3 and 4}
  290.   PORT[ComBase + IER] := 0;              {Disable 8250-Interrupts}
  291.   ClearPendingInterrupts;                {Clean up}
  292.   ComBase := 0;                          {Reset Combase}
  293.   SetIntVec(IntVect[ActivePort], OldV24);{Reset old IV}
  294.   INLINE($FB);                           {STI}
  295. END;
  296.  
  297. {$F+}
  298. PROCEDURE V24ExitProc;
  299.  
  300. BEGIN {V24ExitProc}
  301.   DisableCom;
  302.   ExitProc := OExitHandler;                 { alten Exit-Handler reaktivieren }
  303. END;  {V24ExitProc}
  304. {$F-}
  305.  
  306.  
  307. BEGIN
  308.   {Grund-Init, damit irrtümliche Aufrufe von V24DataAvail nicht zu
  309.    endlosen Ausgaben von Speicherschrott führen!}
  310.   Move(BiosComBaseAdr, ComBaseAdr[Com1], SizeOf(BiosComBaseAdr));
  311.   Move(BiosComBaseAdr, ComBaseAdr[Com3], SizeOf(BiosComBaseAdr));
  312.   Move(BiosComBaseAdr, ComBaseAdr[Com5], SizeOf(BiosComBaseAdr));
  313.   ComBase    := 0;
  314.   V24HP      := Ofs(V24Buff);
  315.   V24TP      := V24HP;
  316.   V24BuffEnd := V24HP + V24BuffSize;
  317.  
  318.   OExitHandler := ExitProc;
  319.   ExitProc     := @V24ExitProc;
  320. END.
  321.  
  322.